<?php
// +----------------------------------------------------------------------
// | ebSIG
// +----------------------------------------------------------------------
// | Copyright (c) 2013-2020 http://www.ebsig.com All rights reserved.
// +----------------------------------------------------------------------
// | Author: liudaojian <liudaojian@ebsig.com>
// +----------------------------------------------------------------------

/**
 * 威富通支付服务
 * @author   liudaojian <liudaojian@ebsig.com>
 * @version 1.0
 */

namespace App\Service\Pay;

use App\Service\XmlService;

use App\Service\Pay\OnlinePayService;

use App\Models\Pay\SysOnlineParameter; //功能配置表

use Illuminate\Support\Facades\Redis as Redis;

class SwiftPassService extends OnlinePayService
{

    const pay_id = 10010; //支付方式id

    private $app_id = '';

    private $mch_id = '7551000001';

    private $sub_app_id = '';

    private $sub_mch_id = '';

    private $md5_key = '9d101c97133837e13dde2d32a5054abb';

    public function __construct($params)
    {
        parent::__construct($params);
    }

    /**
     * 查询支付方式的支付参数
     * @return bool
     */
    private function getPayParameter()
    {

        $pay_data = Redis::get('WDH_PAY_PARAMETER_' . self::pay_id);
        if (!$pay_data) {
            //查询支付方式的支付参数
            $temp_pay = SysOnlineParameter::where('payTypeID', self::pay_id)->first();
            if (!$temp_pay) {
                return false;
            }
            $pay_data = [
                'app_id' => $temp_pay->extend_1,
                'mch_id' => $temp_pay->partnerID,
                'sub_app_id' => $temp_pay->extend_3,
                'sub_mch_id' => $temp_pay->extend_2,
                'md5_key' => $temp_pay->md5_key,
            ];
            Redis::set('WDH_PAY_PARAMETER_' . self::pay_id, 7200, json_encode($pay_data));
        } else {
            $pay_data = json_decode($pay_data);
        }

        $this->app_id = $pay_data['app_id'];
        $this->mch_id = $pay_data['mch_id'];
        $this->sub_app_id = $pay_data['sub_app_id'];
        $this->sub_mch_id = $pay_data['sub_mch_id'];
        $this->md5_key = $pay_data['md5_key'];

        return true;

    }

    /**
     *
     * @return array
     */
    public function request()
    {

        $out_trade_no = $this->get('out_trade_no');//订单号
        $total_fee = $this->get('total_fee'); //订单金额
        $bill_type = $this->get('bill_type'); //订单类型
        $pcustID = $this->get('pcustID'); //会员号
        $notify_url = $this->get('notify_url'); //异步回调地址
        $openId = $this->get('openId');
        $ip = $this->get('ip'); //客户端ip地址
        $attach = $pcustID . '|' . self::pay_id . '|' . $bill_type;

        if (empty($out_trade_no)) {
            return ['code' => 10001, 'message' => '缺少参数：out_trade_no'];
        }
        if (empty($total_fee)) {
            return ['code' => 10002, 'message' => '缺少参数：total_fee'];
        }
        if (!ebsig_is_int($bill_type)) {
            $bill_type = 1;
        }
        if (!ebsig_is_int($pcustID)) {
            return ['code' => 10003, 'message' => '缺少参数：user_id'];
        }
        if (empty($openId)) {
            return ['code' => 10004, 'message' => '缺少参数：openid'];
        }
        if (empty($ip)) {
            return ['code' => 10005, 'message' => '缺少参数：ip'];
        }

        //查询支付方式
        $res = $this->getPayParameter();
        if (!$res) {
            return ['code' => 10006, 'message' => '缺少支付参数'];
        }

        $xml = new XmlService();

        $http_data = [
            'service' => 'pay.weixin.jspay',
            'version' => '2.0',
            'charset' => 'UTF-8',
            'sign_type' => 'MD5',
            'mch_id' => $this->mch_id,
            'is_raw' => 1, //是否原生态 1：是；0：否
            'is_minipg' => 0, //是否小程序支付 值为1，表示小程序支付；不传或值不为1，表示公众账号内支付
            'out_trade_no' => $out_trade_no,
            'body' => $out_trade_no,
            'sub_openid' => $openId,
            'sub_appid' => $this->sub_app_id,
            'attach' => $attach,
            'total_fee' => $total_fee * 100,
            'mch_create_ip' => $ip,
            'notify_url' => $notify_url,
            'nonce_str' => uniqid(),
        ];

        //生成签名
        $http_data['sign'] = $this->createMD5Sign($http_data, $this->md5_key);

        //调用接口，获取支付信息
        $response = $this->postRequest('https://pay.swiftpass.cn/pay/gateway', $xml->encode(['xml' => $http_data]));

        //添加请求日志
        $http_data['unifiedorder'] = $response;
        $this->addLog($out_trade_no, $bill_type, 1, self::pay_id, $http_data);

        if ($response['code'] != 200) {
            return $response;
        }

        $dt = $xml->decode($response['data']);

        if ($dt['status'] != 0) {
            return ['code' => 10001, 'message' => $dt['message']];
        }

        return ['code' => 200, 'message' => 'OK', 'data' => json_decode($dt['pay_info'])];

    }

    /**
     * 回调参数检查
     * @return array
     */
    public function notify()
    {

        $xml = new XmlService();

        //微信返回参数
        $this->set($xml->decode(file_get_contents("php://input")));

        $out_trade_no = $this->get('out_trade_no');
        if (empty($out_trade_no)) {
            return ['code' => 10000, 'message' => $xml->encode( $this->returnMsg('订单号为空') )];
        }

        if ($this->get('return_code') != 'SUCCESS' || $this->get('result_code') != 'SUCCESS') {
            $this->updateLog($out_trade_no, self::pay_id, '支付失败');
            return ['code' => 10000, 'message' => $xml->encode( $this->returnMsg('支付失败') )];
        }

        //查询支付方式数据
        $res = $this->getPayParameter();
        if (!$res) {
            $this->updateLog($out_trade_no, self::pay_id, '缺少支付参数');
            return ['code' => 10001, 'message' => $xml->encode( $this->returnMsg('缺少支付参数') )];
        }

        //检查签名
        $sign = $this->createMD5Sign($this->getAll(), $this->md5_key);
        if ($sign != $this->get('sign')) {
            $this->updateLog($out_trade_no, self::pay_id, '签名错误，签名值：' . $sign);
            return ['code' => 10003, 'message' => $xml->encode( $this->returnMsg('签名错误') )];
        }

        $this->updateLog($out_trade_no, self::pay_id);

        return [
            'code' => 200,
            'message' => $xml->encode( $this->returnMsg('OK', 'SUCCESS') ),
            'data' => [
                'order_no' => $out_trade_no,
                'pay_code' => $this->get('transaction_id'),
                'pay_time' => date('Y-m-d H:i:s', strtotime($this->get('time_end'))),
                'total_fee' => round($this->get('total_fee') / 100, 2)
            ]
        ];

    }

    /**
     * post请求
     * GuzzleHttp\Client库的post请求必须使用数组，微信支付post请求数据是xml格式
     * @param string $url 接口地址
     * @param string $data 请求数据
     * @param null $http_opts
     * @return array
     */
    public function postRequest( $url, $data, $http_opts = null ) {

        if (!isset($url) || empty($url)) {
            return array( 'code' => 400, 'message' => '缺少请求链接' );
        }
        if (!isset($data)) {
            return array( 'code' => 400 ,'message' => '缺少请求参数');
        }

        //解析链接，判断请求协议
        //$parse_url_array = parse_url($url);

        $curl_handler = curl_init();

        $options = array(
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_CONNECTTIMEOUT => 15,
            CURLOPT_HEADER	 => false,
            CURLOPT_POST => TRUE,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_POSTFIELDS => $data
        );

        if (is_array($http_opts)) {
            foreach ($http_opts as $key => $value) {
                $options[$key] = $value;
            }
        }

        curl_setopt_array($curl_handler, $options);
        $curl_result = curl_exec($curl_handler); //获取URL站点内容 并打印出来
        $curl_http_status = curl_getinfo($curl_handler,CURLINFO_HTTP_CODE); //获取最后一次收到的HTTP代码
        $curl_http_info = curl_getinfo($curl_handler);

        if ($curl_result == false) {
            $error = curl_error($curl_handler);
            curl_close($curl_handler);
            return array('code' => $curl_http_status, 'message' => $error);
        }
        curl_close($curl_handler);

        $encode = mb_detect_encoding($curl_result, array('ASCII', 'UTF-8','GB2312', 'GBK', 'BIG5')); //进行编码识别
        if ($encode != 'UTF-8') {
            $curl_result = iconv($encode, 'UTF-8', $curl_result);
        }

        $result = json_decode($curl_result, true);

        if (is_null($result)) {
            $result = $curl_result;
        }

        return array('code' => $curl_http_status, 'message' => 'ok', 'data' => $result);

    }

    /**
     * 生成微信返回数据
     * @param string $msg 错误消息
     * @param string $code 错误代码
     * @return array
     */
    private function returnMsg($msg, $code='FAIL')
    {
        return ['xml' => [ 'return_code' => $code, 'return_msg' => $msg]];
    }

}